<template>
    <!-- component/calendar/calendar.wxml -->
    <view class="calendar">
        <view class="title">
            <view class="header-wrap">
                <view class="flex">
                    <view class="title">{{ title }}</view>
                    <view class="month">
                        <block v-if="title">(</block>
                        {{ selectDay.year }}年{{ selectDay.month }}月
                        <block v-if="title">)</block>
                    </view>
                </view>
                <block v-if="goNow">
                    <view v-if="open && !(nowDay.year == selectDay.year && nowDay.month == selectDay.month && nowDay.day == selectDay.day)" class="today" @tap="switchNowDate">
                        今日
                    </view>
                </block>
            </view>
        </view>

        <!-- 日历头部 -->
        <view class="flex-around calendar-week">
            <view class="view">一</view>
            <view class="view">二</view>
            <view class="view">三</view>
            <view class="view">四</view>
            <view class="view">五</view>
            <view class="view">六</view>
            <view class="view">日</view>
        </view>
        <!-- 日历主体 -->
        <swiper class="swiper" :style="'height:' + swiperHeight + 'rpx'" @change="swiperChange" :circular="true" :current="swiperCurrent" :duration="swiperDuration">
            <swiper-item v-for="(listItem, listIndex) in [dateList0, dateList1, dateList2]" :key="listIndex">
                <view class="flex-start flex-wrap calendar-main" :style="'height:' + (listItem.length / 7) * 82 + 'rpx'">
                    <view class="day f fac fpc" v-for="(item, index) in listItem" :key="index">
                        <!-- catchtap="selectChange" -->

                        <view
                            :class="
                                'bg ' +
                                (item.month === selectDay.month
                                    ? spotMap['y' + item.year + 'm' + item.month + 'd' + item.day]
                                        ? spotMap['y' + item.year + 'm' + item.month + 'd' + item.day]
                                        : ''
                                    : '') +
                                ' ' +
                                (item.year === nowDay.year && item.month === nowDay.month && item.day === nowDay.day ? 'now' : '') +
                                ' ' +
                                (item.year === selectDay.year && item.month === selectDay.month
                                    ? item.day === selectDay.day && oldCurrent === listIndex
                                        ? 'select'
                                        : ''
                                    : 'other-month')
                            "
                            :data-day="item.day"
                            :data-year="item.year"
                            :data-month="item.month"
                            v-if="!item.sign"
                        >
                            {{ item.day }}
                        </view>

                        <van-icon v-else color="orange" size="40rpx" name="checked" />

                        <!-- <view class=" font_w text-orange">√</view> -->
                    </view>
                </view>
            </swiper-item>
        </swiper>
        <view style="width: 100%; display: flex; justify-content: center">
            <view :class="isSign ? 'btn_signed' : 'btn_sign'" @tap="parseEventDynamicCode($event, isSign ? '' : 'signed')">{{ isSign ? '今日已签到' : '去签到' }}</view>
        </view>
        <!-- <view catchtap="openChange" class="flex list-open">
        <view class="icon {{open?'fold':'unfold'}}"></view>
    </view> -->
    </view>
</template>

<script>
// component/calendar/calendar.js
export default {
    data() {
        return {
            selectDay: {
                day: '',
                year: '',
                month: ''
            },

            //选中时间
            nowDay: {
                year: '',
                month: '',
                day: ''
            },

            //现在时间
            open: true,

            swiperCurrent: 1,

            //选中时间
            oldCurrent: 1,

            //之前选中时间
            dateList0: [],

            //0位置的日历数组
            dateList1: [],

            //1位置的日历数组
            dateList2: [],

            //2位置的日历数组
            swiperDuration: 500,

            swiperHeight: 0,
            backChange: false,

            //跳过change切换
            isSign: false,

            showRl: '',
            listName: '',
            listIndex: [],
            listItem: []
        };
    },
    /**
     * 组件的属性列表
     */
    props: {
        spotMap: {
            //标点的日期
            type: Object,
            default: () => ({})
        },
        defaultTime: {
            //标记的日期，默认为今日
            type: String,
            default: ''
        },
        title: {
            //标题
            type: String,
            default: ''
        },
        goNow: {
            // 是否有快速回到今天的功能
            type: Boolean,
            default: true
        }
    },
    /**
     * 组件的方法列表
     */
    methods: {
        attached() {
            let now = this.defaultTime ? new Date(this.defaultTime) : new Date();
            let selectDay = {
                year: now.getFullYear(),
                month: now.getMonth() + 1,
                day: now.getDate()
            };
            this.setData({
                nowDay: {
                    year: now.getFullYear(),
                    month: now.getMonth() + 1,
                    day: now.getDate()
                }
            });
            this.setMonth(selectDay.year, selectDay.month, selectDay.day);
            this.updateList(now, -1, 0);
            this.updateList(now, 0, 1);
            this.updateList(now, 1, 2);
            this.setSwiperHeight(1);
            this.setData({
                showRl: !this.showRl
            });
            // 是否在缓存中已签到
            let isSign = false;
            let days = uni.getStorageSync('signDays');
            if (days) {
                let d = this.nowDay.day;
                let m = this.nowDay.month < 10 ? '0' + this.nowDay.month : this.nowDay.month;
                let y = this.nowDay.year;
                days.forEach((e) => {
                    if (e == y + '-' + m + '-' + d) {
                        isSign = true;
                    }
                });
            }
            this.setData({
                isSign: isSign
            });
        },

        swiperChange(e) {
            // 日历滑动时触发的方法
            if (this.backChange) {
                this.setData({
                    backChange: false
                });
                return;
            }
            //计算第三个索引
            let rest = 3 - e.detail.current - this.oldCurrent;
            let dif = e.detail.current - this.oldCurrent;
            let date;
            if (dif === -2 || (dif > 0 && dif !== 2)) {
                //向右划的情况，日期增加
                if (this.open) {
                    date = new Date(this.selectDay.year, this.selectDay.month);
                    this.setMonth(date.getFullYear(), date.getMonth() + 1, undefined);
                    this.getIndexList({
                        setYear: this.selectDay.year,
                        setMonth: this.selectDay.month,
                        dateIndex: rest
                    });
                } else {
                    date = new Date(this.selectDay.year, this.selectDay.month - 1, this.selectDay.day + 7);
                    this.setMonth(date.getFullYear(), date.getMonth() + 1, date.getDate());
                    this.getIndexList({
                        setYear: this.selectDay.year,
                        setMonth: this.selectDay.month - 1,
                        setDay: this.selectDay.day + 7,
                        dateIndex: rest
                    });
                }
            } else {
                //向左划的情况，日期减少
                if (this.open) {
                    date = new Date(this.selectDay.year, this.selectDay.month - 2);
                    this.setMonth(date.getFullYear(), date.getMonth() + 1, undefined);
                    this.getIndexList({
                        setYear: this.selectDay.year,
                        setMonth: this.selectDay.month - 2,
                        dateIndex: rest
                    });
                } else {
                    date = new Date(this.selectDay.year, this.selectDay.month - 1, this.selectDay.day - 7);
                    this.setMonth(date.getFullYear(), date.getMonth() + 1, date.getDate());
                    this.getIndexList({
                        setYear: this.selectDay.year,
                        setMonth: this.selectDay.month - 1,
                        setDay: this.selectDay.day - 7,
                        dateIndex: rest
                    });
                }
            }
            this.setData({
                oldCurrent: e.detail.current
            });
            this.setSwiperHeight(e.detail.current);
        },

        setSwiperHeight(index) {
            // 根据指定位置数组的大小计算长度
            this.setData({
                swiperHeight: (this[`dateList${index}`].length / 7) * 82 + 40
            });
        },

        //更新指定的索引和月份的列表
        getIndexList({ setYear, setMonth, setDay = void 0, dateIndex }) {
            let appointMonth;
            if (setDay) {
                appointMonth = new Date(setYear, setMonth, setDay);
            } else {
                appointMonth = new Date(setYear, setMonth);
            }
            let listName = `dateList${dateIndex}`;
            this.setData({
                [listName]: this.dateInit({
                    setYear: appointMonth.getFullYear(),
                    setMonth: appointMonth.getMonth() + 1,
                    setDay: appointMonth.getDate(),
                    hasBack: true
                })
            });
        },

        //设置月份
        setMonth(setYear, setMonth, setDay) {
            const day = Math.min(new Date(setYear, setMonth, 0).getDate(), this.selectDay.day);
            if (this.selectDay.year !== setYear || this.selectDay.month !== setMonth) {
                const data = {
                    selectDay: {
                        year: setYear,
                        month: setMonth,
                        day: setDay ? setDay : day
                    }
                };
                if (!setDay) {
                    data.open = true;
                }
                this.setData(data, () => {
                    this.$emit('selectDay', {
                        detail: this.selectDay
                    });
                });
            } else {
                const data = {
                    selectDay: {
                        year: setYear,
                        month: setMonth,
                        day: setDay ? setDay : day
                    }
                };
                this.setData(data, () => {
                    this.$emit('selectDay', {
                        detail: this.selectDay
                    });
                });
            }
        },

        //展开收起
        openChange() {
            this.setData({
                open: !this.open
            });
            this.$emit('aaa', {
                detail: {
                    a: 0
                }
            });
            // 更新数据
            const selectDate = new Date(this.selectDay.year, this.selectDay.month - 1, this.selectDay.day);
            if (this.oldCurrent === 0) {
                this.updateList(selectDate, -1, 2);
                this.updateList(selectDate, 0, 0);
                this.updateList(selectDate, 1, 1);
            } else if (this.oldCurrent === 1) {
                this.updateList(selectDate, -1, 0);
                this.updateList(selectDate, 0, 1);
                this.updateList(selectDate, 1, 2);
            } else if (this.oldCurrent === 2) {
                this.updateList(selectDate, -1, 1);
                this.updateList(selectDate, 0, 2);
                this.updateList(selectDate, 1, 0);
            }
            this.setSwiperHeight(this.oldCurrent);
        },

        // 选中并切换今日日期
        switchNowDate() {
            const now = new Date();
            const selectDate = new Date(this.selectDay.year, this.selectDay.month - 1, this.selectDay.day);
            let dateDiff = (selectDate.getFullYear() - now.getFullYear()) * 12 + (selectDate.getMonth() - now.getMonth());
            let diff = dateDiff === 0 ? 0 : dateDiff > 0 ? -1 : 1;
            const diffSum = (x) => (3 + (x % 3)) % 3;
            if (this.oldCurrent === 0) {
                this.updateList(now, -1, diffSum(2 + diff));
                this.updateList(now, 0, diffSum(0 + diff));
                this.updateList(now, 1, diffSum(1 + diff));
            } else if (this.oldCurrent === 1) {
                this.updateList(now, -1, diffSum(0 + diff));
                this.updateList(now, 0, diffSum(1 + diff));
                this.updateList(now, 1, diffSum(2 + diff));
            } else if (this.oldCurrent === 2) {
                this.updateList(now, -1, diffSum(1 + diff));
                this.updateList(now, 0, diffSum(2 + diff));
                this.updateList(now, 1, diffSum(0 + diff));
            }
            this.setData({
                swiperCurrent: diffSum(this.oldCurrent + diff),
                oldCurrent: diffSum(this.oldCurrent + diff),
                backChange: dateDiff !== 0
            });
            this.setData(
                {
                    selectDay: {
                        year: now.getFullYear(),
                        month: now.getMonth() + 1,
                        day: now.getDate()
                    }
                },
                () => {
                    this.$emit('selectDay', {
                        detail: this.selectDay
                    });
                }
            );
            this.setSwiperHeight(this.oldCurrent);
        },

        //日历主体的渲染方法
        dateInit(
            { setYear, setMonth, setDay = this.selectDay.day, hasBack = false } = {
                setYear: this.selectDay.year,
                setMonth: this.selectDay.month,
                setDay: this.selectDay.day,
                hasBack: false
            }
        ) {
            let dateList = []; //需要遍历的日历数组数据
            let now = new Date(setYear, setMonth - 1); //当前月份的1号
            let startWeek = now.getDay(); //目标月1号对应的星期
            let resetStartWeek = startWeek == 0 ? 6 : startWeek - 1; //重新定义星期将星期天替换为6其余-1
            let dayNum = new Date(setYear, setMonth, 0).getDate(); //当前月有多少天
            let forNum = Math.ceil((resetStartWeek + dayNum) / 7) * 7; //当前月跨越的周数
            let selectDay = setDay ? setDay : this.selectDay.day;
            let list = uni.getStorageSync('signDays');
            this.$emit('getDateList', {
                detail: {
                    setYear: now.getFullYear(),
                    setMonth: now.getMonth() + 1
                }
            });
            if (this.open) {
                //展开状态，需要渲染完整的月份
                for (let i = 0; i < forNum; i++) {
                    const now2 = new Date(now);
                    now2.setDate(i - resetStartWeek + 1);
                    let d = now2.getDate();
                    let m = now2.getMonth() + 1 < 10 ? '0' + (now2.getMonth() + 1) : now2.getMonth() + 1;
                    let y = now2.getFullYear();
                    let obj = {};
                    obj = {
                        sign: list.includes(y + '-' + m + '-' + d),
                        day: now2.getDate(),
                        month: now2.getMonth() + 1,
                        year: now2.getFullYear()
                    };
                    dateList[i] = obj;
                }
            } else {
                //非展开状态，只需要渲染当前周
                for (let i = 0; i < 7; i++) {
                    const now2 = new Date(now);
                    //当前周的7天
                    now2.setDate(Math.ceil((selectDay + (startWeek - 1)) / 7) * 7 - 6 - (startWeek - 1) + i);
                    let obj = {};
                    obj = {
                        sign: list.includes(now2.getFullYear() + '-' + (now2.getMonth() + 1) < 10 ? '0' + now2.getMonth() + 1 : now2.getMonth() + 1 + '-' + now2.getDate()),
                        day: now2.getDate(),
                        month: now2.getMonth() + 1,
                        year: now2.getFullYear()
                    };
                    dateList[i] = obj;
                }
            }
            if (hasBack) {
                return dateList;
            }
            this.setData({
                dateList1: dateList
            });
        },

        //一天被点击时
        selectChange(e) {
            const year = e.currentTarget.dataset.year;
            const month = e.currentTarget.dataset.month;
            const day = e.currentTarget.dataset.day;
            const selectDay = {
                year: year,
                month: month,
                day: day
            };
            if (this.open && (this.selectDay.year !== year || this.selectDay.month !== month)) {
                if (year * 12 + month > this.selectDay.year * 12 + this.selectDay.month) {
                    // 下个月
                    if (this.oldCurrent == 2) {
                        this.setData({
                            swiperCurrent: 0
                        });
                    } else {
                        this.setData({
                            swiperCurrent: this.oldCurrent + 1
                        });
                    }
                } else {
                    // 点击上个月
                    if (this.oldCurrent == 0) {
                        this.setData({
                            swiperCurrent: 2
                        });
                    } else {
                        this.setData({
                            swiperCurrent: this.oldCurrent - 1
                        });
                    }
                }
                this.setData(
                    {
                        ['selectDay.day']: day
                    },
                    () => {
                        this.$emit('selectDay', {
                            detail: this.selectDay
                        });
                    }
                );
            } else if (this.selectDay.day !== day) {
                this.setData(
                    {
                        selectDay: selectDay
                    },
                    () => {
                        this.$emit('selectDay', {
                            detail: this.selectDay
                        });
                    }
                );
            }
        },

        updateList(date, offset, index) {
            if (this.open) {
                //打开状态
                const setDate = new Date(date.getFullYear(), date.getMonth() + offset * 1); //取得当前日期的上个月日期
                this.getIndexList({
                    setYear: setDate.getFullYear(),
                    setMonth: setDate.getMonth(),
                    dateIndex: index
                });
            } else {
                const setDate = new Date(date.getFullYear(), date.getMonth(), date.getDate() + offset * 7); //取得当前日期的七天后的日期
                this.getIndexList({
                    setYear: setDate.getFullYear(),
                    setMonth: setDate.getMonth(),
                    setDay: setDate.getDate(),
                    dateIndex: index
                });
            }
        },

        signed() {
            let list = uni.getStorageSync('signDays');
            let d = this.nowDay.day;
            let m = this.nowDay.month < 10 ? '0' + this.nowDay.month : this.nowDay.month;
            let y = this.nowDay.year;
            if (list.length) {
                list.push(y + '-' + m + '-' + d);
                uni.setStorageSync('signDays', list);
            } else {
                uni.setStorageSync('signDays', [y + '-' + m + '-' + d]);
            }
            let now = this.defaultTime ? new Date(this.defaultTime) : new Date();
            uni.showToast({
                title: '签到成功'
            });
            this.setData({
                isSign: true
            });
            this.updateList(now, 0, 1);
        }
    },
    mounted() {
        // 处理小程序 attached 生命周期
        this.attached();
    },
    created: function () {}
};
</script>
<style>
@import './index.css';
</style>
